/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package utility;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.lang.reflect.*;
import org.apache.hadoop.io.GenericWritable;
import org.apache.hadoop.io.MapWritable;
import org.apache.hadoop.io.Writable;

/**
 *
 * @author liuyu
 */
// not comaprable
//implements
//GenericWritable
//MapWritable
public class Tuple<T1, T2, T3> implements Writable {

    private T1 first;
    private T2 second;
    private T3 third;

    public Tuple() {
    }

    public Tuple(T1 fst, T2 snd, T3 trd) {
        first = fst;
        second = snd;
        third = trd;
    }
        public Tuple(Tuple<T1, T2, T3> other) {
        first = other.first;
        second = other.second;
        third = other.third;
    }

    // for special case
    public static Tuple<Float, Float, Integer> Sum(Tuple<Float, Float, Integer> v1, Tuple<Float, Float, Integer> v2) {
        if (v1 == null || v2 == null) throw new NullPointerException("input can not be null!");
     //   if (v2 == null) return v1;
        Tuple<Float, Float, Integer> rst = new Tuple<Float, Float, Integer>();
        rst.Set1st(v1.Get1st() + v2.Get1st());
        rst.Set2nd(v1.Get2nd() + v2.Get2nd());
        rst.Set3rd(v1.Get3rd() + v2.Get3rd());
        return rst;
    }


    @Override
    public String toString() {
        return   first  + "\t " + second  + "\t " + third ;
    }

    public void Set1st(T1 fst) {
        first = fst;
    }

    public void Set2nd(T2 in) {
        second = in;
    }

    public void Set3rd(T3 in) {
        third = in;
    }

    public T1 Get1st() {
        return first;
    }

    public T2 Get2nd() {
        return second;
    }

    public T3 Get3rd() {
        return third;
    }

    public void write(DataOutput out) throws IOException {
        if (this.first instanceof Integer) {
            out.writeInt((Integer) first);
        } else if (this.first instanceof Float) {
            out.writeFloat((Float) first);
        } else if (this.first instanceof Double) {
            out.writeDouble((Double) first);
        } else if (this.first instanceof Boolean) {
            out.writeBoolean((Boolean) first);
        } else if (this.first instanceof Long) {
            out.writeLong((Long) first);
        }

        //second
        if (this.second instanceof Integer) {
            out.writeInt((Integer) second);
        } else if (this.second instanceof Float) {
            out.writeFloat((Float) second);
        } else if (this.second instanceof Double) {
            out.writeDouble((Double) second);
        } else if (this.second instanceof Boolean) {
            out.writeBoolean((Boolean) second);
        } else if (this.second instanceof Long) {
            out.writeLong((Long) second);
        }

        //third
        if (this.third instanceof Integer) {
            out.writeInt((Integer) third);
        } else if (this.third instanceof Float) {
            out.writeFloat((Float) third);
        } else if (this.third instanceof Double) {
            out.writeDouble((Double) third);
        } else if (this.third instanceof Boolean) {
            out.writeBoolean((Boolean) third);
        } else if (this.third instanceof Long) {
            out.writeLong((Long) third);
        }

    }

    public void readFields(DataInput in) throws IOException {
      //  TypeVariable[] types=  this.getClass().getTypeParameters();
        first = (T1) Float.valueOf(in.readFloat());
        second = (T2) Float.valueOf(in.readFloat());
        third = (T3) Integer.valueOf(in.readInt());
        /*
        if (this.first instanceof Integer) {
            first = (T1) Integer.valueOf(in.readInt());
        } else if (this.first instanceof Long) {
            first = (T1) Long.valueOf(in.readLong());
        } else if (this.first instanceof Double) {
            first = (T1) Double.valueOf(in.readDouble());
        } else if (this.first instanceof Float) {
            first = (T1) Float.valueOf(in.readFloat());
        }

        // second
        if (this.second instanceof Integer) {
            second = (T2) Integer.valueOf(in.readInt());
        } else if (this.second instanceof Long) {
            second = (T2) Long.valueOf(in.readLong());
        } else if (this.second instanceof Double) {
            second = (T2) Double.valueOf(in.readDouble());
        } else if (this.second instanceof Float) {
            second = (T2) Float.valueOf(in.readFloat());
        }
        // third
        if (this.third instanceof Integer) {
            third = (T3) Integer.valueOf(in.readInt());
        } else if (this.third instanceof Long) {
            third = (T3) Long.valueOf(in.readLong());
        } else if (this.third instanceof Double) {
            third = (T3) Double.valueOf(in.readDouble());
        } else if (this.third instanceof Float) {
            third = (T3) Float.valueOf(in.readFloat());
        }

         * 
         */
    }

    protected Class<? extends Writable>[] getTypes() {
        Class< Writable>[] types = new Class[3];
        types[0] =  (Class<Writable>) first.getClass();
        types[1] =  (Class<Writable>) second.getClass();
        types[2] =  (Class<Writable>) third.getClass();

        return types;
    }
}
